package com.immediatus.engine.input;

import android.view.MotionEvent;
import com.immediatus.engine.contracts.ITouchController;
import com.immediatus.engine.util.RunnablePoolItem;
import com.immediatus.engine.util.RunnablePoolUpdateHandler;
import com.immediatus.options.TouchOptions;

public abstract class BaseTouchController implements ITouchController{

    private ITouchEventCallback _touchEventCallback;
    private boolean _runOnUpdateThread;

    private final RunnablePoolUpdateHandler<TouchEventRunnablePoolItem> _touchEventRunnablePoolUpdateHandler = new RunnablePoolUpdateHandler<TouchEventRunnablePoolItem>(){
        @Override
        protected TouchEventRunnablePoolItem onAllocatePoolItem(){
            return new TouchEventRunnablePoolItem();
        }
    };

    public BaseTouchController(){
    }

    @Override
    public void setTouchEventCallback(final ITouchEventCallback touchEventCallback_){
        this._touchEventCallback = touchEventCallback_;
    }

    @Override
    public void reset(){
        if (this._runOnUpdateThread){
            this._touchEventRunnablePoolUpdateHandler.reset();
        }
    }

    @Override
    public void onUpdate(final float secondsElapsed_){
        if (this._runOnUpdateThread){
            this._touchEventRunnablePoolUpdateHandler.onUpdate(secondsElapsed_);
        }
    }

    protected boolean fireTouchEvent(final float x_, final float y_, final int action_, final int pointerID_, final MotionEvent e_){
        final boolean handled;

        if (this._runOnUpdateThread){
            final TouchEvent touchEvent = TouchEvent.obtain(x_, y_, action_, pointerID_, MotionEvent.obtain(e_));

            final TouchEventRunnablePoolItem touchEventRunnablePoolItem = this._touchEventRunnablePoolUpdateHandler.obtainPoolItem();
            touchEventRunnablePoolItem.set(touchEvent);
            this._touchEventRunnablePoolUpdateHandler.postPoolItem(touchEventRunnablePoolItem);

            handled = true;
        } else{
            final TouchEvent touchEvent = TouchEvent.obtain(x_, y_, action_, pointerID_, e_);
            handled = this._touchEventCallback.onTouchEvent(touchEvent);
            touchEvent.recycle();
        }

        return handled;
    }

    @Override
    public void applyTouchOptions(final TouchOptions touchOptions_){
        this._runOnUpdateThread = touchOptions_.isRunOnUpdateThread();
    }

    class TouchEventRunnablePoolItem extends RunnablePoolItem{
        private TouchEvent _touchEvent;

        public void set(final TouchEvent e_){
            this._touchEvent = e_;
        }

        @Override
        public void run(){
            BaseTouchController.this._touchEventCallback.onTouchEvent(this._touchEvent);
        }

        @Override
        protected void onRecycle(){
            super.onRecycle();
            final TouchEvent touchEvent = this._touchEvent;
            touchEvent.getMotionEvent().recycle();
            touchEvent.recycle();
        }
    }
}
